using System;
using System.Collections.Generic;
using System.Text;
using System.Security;
using System.Runtime.InteropServices;
using System.ComponentModel;

namespace Ricciolo.PaperBoy.UI.Interop
{
    public class NativeMethods
    {

        [StructLayout(LayoutKind.Sequential)]
        public struct RECT
        {
            public int left;
            public int top;
            public int right;
            public int bottom;

            public RECT(int left, int top, int right, int bottom)
            {
                this.left = left;
                this.top = top;
                this.right = right;
                this.bottom = bottom;
            }

            public bool IsEmpty
            {
                get
                {
                    if (this.left < this.right)
                    {
                        return (this.top >= this.bottom);
                    }
                    return true;
                }
            }

        }
    }

    public class SafeNativeMethods
    {
        internal static void GetWindowRect(HandleRef hWnd, out NativeMethods.RECT rect)
        {
            if (!SafeNativeMethods.IntGetWindowRect(hWnd, out rect))
            {
                throw new Win32Exception();
            }
        }

        [DllImport("user32.dll", EntryPoint = "GetWindowRect", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
        public static extern bool IntGetWindowRect(HandleRef hWnd, out NativeMethods.RECT rect);

    }

    public class UnsafeNativeMethods
    {
        public static IntPtr GetDC(HandleRef hWnd)
        {
            IntPtr ptr1 = UnsafeNativeMethods.IntGetDC(hWnd);
            if (ptr1 == IntPtr.Zero)
            {
                throw new Win32Exception();
            }
            //return HandleCollector.Add(ptr1, NativeMethods.CommonHandles.HDC);
            return ptr1;
        }

        [SecurityCritical, SuppressUnmanagedCodeSecurity, DllImport("user32.dll", EntryPoint = "GetDC", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
        private static extern IntPtr IntGetDC(HandleRef hWnd);

        [SecurityCritical, SuppressUnmanagedCodeSecurity, DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
        public static extern bool IsWindow(HandleRef hWnd);

        [SecurityCritical, SuppressUnmanagedCodeSecurity, DllImport("gdi32.dll", EntryPoint = "CreateCompatibleDC", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern IntPtr CriticalCreateCompatibleDC(HandleRef hDC);

        [SecurityCritical, SuppressUnmanagedCodeSecurity, DllImport("gdi32.dll", EntryPoint = "CreateCompatibleBitmap", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
        public static extern IntPtr CriticalCreateCompatibleBitmap(HandleRef hDC, int width, int height);

        [SecurityCritical, SuppressUnmanagedCodeSecurity, DllImport("gdi32.dll", EntryPoint = "SelectObject", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
        public static extern IntPtr CriticalSelectObject(HandleRef hdc, IntPtr obj);

        [SuppressUnmanagedCodeSecurity, SecurityCritical, DllImport("gdi32.dll", EntryPoint = "GetStockObject", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern IntPtr CriticalGetStockObject(int stockObject);

        [SuppressUnmanagedCodeSecurity, SecurityCritical, DllImport("user32.dll", EntryPoint = "PrintWindow", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
        public static extern bool CriticalPrintWindow(HandleRef hWnd, HandleRef hDC, int flags);

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        internal static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);

        [SuppressUnmanagedCodeSecurity, SecurityCritical, DllImport("user32.dll", EntryPoint = "RedrawWindow", CharSet = CharSet.Auto, ExactSpelling = true)]
        public static extern bool CriticalRedrawWindow(HandleRef hWnd, IntPtr lprcUpdate, IntPtr hrgnUpdate, int flags);

        [SecurityCritical]
        public static int ReleaseDC(HandleRef hWnd, HandleRef hDC)
        {
            //HandleCollector.Remove((IntPtr)hDC, NativeMethods.CommonHandles.HDC);
            return UnsafeNativeMethods.IntReleaseDC(hWnd, hDC);
        }

        [SuppressUnmanagedCodeSecurity, SecurityCritical, DllImport("user32.dll", EntryPoint = "ReleaseDC", CharSet = CharSet.Auto, ExactSpelling = true)]
        private static extern int IntReleaseDC(HandleRef hWnd, HandleRef hDC);

        [SecurityCritical]
        public static void DeleteObject(HandleRef hObject)
        {
            //HandleCollector.Remove((IntPtr)hObject, NativeMethods.CommonHandles.GDI);
            if (!UnsafeNativeMethods.IntDeleteObject(hObject))
            {
                throw new Win32Exception();
            }
        }

        [SecurityCritical, SuppressUnmanagedCodeSecurity, DllImport("gdi32.dll", EntryPoint = "DeleteObject", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
        public static extern bool IntDeleteObject(HandleRef hObject);

        [SecurityCritical]
        public static void CriticalDeleteDC(HandleRef hDC)
        {
            //HandleCollector.Remove((IntPtr)hDC, NativeMethods.CommonHandles.HDC);
            if (!UnsafeNativeMethods.IntCriticalDeleteDC(hDC))
            {
                throw new Win32Exception();
            }
        }

        [SuppressUnmanagedCodeSecurity, SecurityCritical, DllImport("gdi32.dll", EntryPoint = "DeleteDC", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
        private static extern bool IntCriticalDeleteDC(HandleRef hDC);

        [SecurityCritical, SuppressUnmanagedCodeSecurity, DllImport("user32.dll", EntryPoint = "FillRect", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern int CriticalFillRect(IntPtr hdc, ref NativeMethods.RECT rcFill, IntPtr brush);

        internal static void Win32BitBlt(HandleRef handledestination, int width, int height, HandleRef handleSource, int operationCode)
        {
            if (!UnsafeNativeMethods.BitBlt(handledestination, 0, 0, width, height, handleSource, 0, 0, operationCode))
            {
                throw new Win32Exception();
            }
        }

        [DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
        public static extern bool BitBlt(HandleRef hDC, int x, int y, int nWidth, int nHeight, HandleRef hSrcDC, int xSrc, int ySrc, int dwRop);

        public const int SRCCOPY = 0xcc0020;

        [SecurityCritical, SuppressUnmanagedCodeSecurity, DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
        public static extern bool InvalidateRect(HandleRef hWnd, ref NativeMethods.RECT rect, bool erase);


    }
}
